﻿using System.Security;
using System.IO;
using System.Reflection;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using LOMM3API;
using LOMM3Shell.Properties;

namespace LOMM3Shell
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        private static int SHELLVERSION = 3;

        private List<LOMMGame> _Games = new List<LOMMGame>();

        private WindowSplash _Splash;
        
        protected override void OnStartup(StartupEventArgs e)
        {   //=================================================================
            base.OnStartup(e);

            _Splash = new WindowSplash();
            _Splash.Show();
            
            foreach (LOMMGame game in GameModules())
            {
                // Get the games that want to run loaded up.  
                if (game.CanRun()) 
                  {
                      _Splash.AddEvent(new SplashEvent(game, "Ready to run"));
                      _Games.Add(game);                      
                  }
                  else
                  {
                      _Splash.AddEvent(new SplashEvent(game, "Declined to run"));
                  }

                // Have the running game(s) init themselves. They return some messages to show
                foreach (String s in game.Initialize())
                {
                    _Splash.AddEvent(new SplashEvent(game, s));
                }
            }
            
            
            //_Splash.Close();
            //_Splash = null;

            return;
        }
        
        private IEnumerable<LOMMGame> GameModules()
        {   //=================================================================
            // Load game modules. For each assembly found in the GameDirectory check
            // for any type that has the LOMMGame attribute and instantiate it.
            // Stick these in our list for now. We'll deal with them later.
            String strPluginFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + Settings.Default.PluginDir;
            strPluginFolder = @"C:\Dev\src\LOMM\LOTROMusicManager\LOMM3x\GameLOTRO\bin\3.0 Debug";
            DirectoryInfo di = new DirectoryInfo(strPluginFolder);
            foreach (FileInfo fi in di.GetFiles("*.dll"))
            {
                Assembly ass = null;
                try
                {
                    ass = Assembly.LoadFile(fi.FullName);
                }
                // Reasons that we may not be able to load the assembly.
                // These are all OK to ignore and move on (to the next file)
                catch (ArgumentNullException)   {continue;}
                catch (FileLoadException)       {continue;}
                catch (FileNotFoundException)   {continue;}
                catch (BadImageFormatException) {continue;}

                Type[] types = null;
                try 
                {
                    types = ass.GetTypes();
                }
                // Okay to ignore this. Just means some types were weird
                // They come back NULL in the array and we ignore them
                catch (ReflectionTypeLoadException) {}

                foreach (Type t in types)
                {
                    foreach (object att in t.GetCustomAttributes(true))
                    {
                        LOMMGame game = null;
                        try
                        {
                            if (att is LOMMGameAttribute)
                            {
                                LOMMGameAttribute lga = att as LOMMGameAttribute;
                                if (lga != null && lga.ShellVersion <= SHELLVERSION)
                                {
                                    ConstructorInfo ci = t.GetConstructor(System.Type.EmptyTypes);
                                    game = ci.Invoke(System.Type.EmptyTypes) as LOMMGame;
                                }
                            }
                        }
                        // GetInterfaces threw, just move on
                        catch (TargetInvocationException)     {}
                        // GetCustomAttributes threw. Just ignore. Nothing else we could do.
                        catch (InvalidOperationException)     {}
                        catch (TypeLoadException)             {}
                        // GetConstructor threw
                        catch (ArgumentNullException)         {}
                        // Invoke threw
                        catch (MethodAccessException)         {}
                        catch (MemberAccessException)         {}
                        catch (ArgumentException)             {}
                        catch (TargetParameterCountException) {}
                        catch (NotSupportedException)         {}
                        catch (SecurityException)             {}

                        if (game != null) yield return game;
                    }
                }
            }
        }
    }
}
